Widget 類別的原始碼上有標注 @immutable
,這個標注的意思是不可變的;簡單的來說這個類別裡的類別屬性必需宣告成 final
,經賦值後就不可改變。
@immutable
abstract class Widget extends DiagnosticableTree {
/// Initializes [key] for subclasses.
const Widget({ this.key });
...
在先前的範例中,我們有使用過 StatelessWidget
,這類型的控件通常只需要定義佈局內容,而 StatefulWidget
內部使用 State
來處理狀態變化的管理,可以在收到異動後透過 setState
通知 Flutter 重新渲染畫面。
Widget 在設計上是 immutable
的,也就是說控件在經過創建後就不能夠修改,所以 Flutter 設計上將狀態管理的這件事情交由 State
類別來處理。
繼承 StatefulWidget 的控件需要覆寫掉 createState
這個方式,回傳自己定義的 State
對象,在 State
中,我們可以定義想要的屬性,並且定義控件 build
方法,這個方法與 StatelessWidget
的 build
行為一樣是用來定義佈局的內容。
StatefulWidget
的實作可以參考下面時間控件的寫法,在狀態中我們有個字串類別的 _now
屬性用來顯示目前的時間。TimeModel
類別 mixin ChangeNotifier,每隔一秒鐘就會觸發時間變更的事件。
我們在生命週期階段的 initState
監聽時間變更的事件,並在收到事件後更新_now
的資料並呼叫setState
更新畫面。
class Clock extends StatefulWidget {
// 這邊的 key 是底層 widget canUpdate 方法有關
const Clock({Key? key}) : super(key: key);
@override
_Clock createState() => _Clock();
}
class _Clock extends State<Clock> {
// TimeModel 自己實作的時間類別
// 此類別 mixin ChangeNotifier 類別,提供`觀察者模式`的特性
final TimeModel time = TimeModel();
String _now = "";
// 透過呼叫 setState 通知狀態已異動
_updateTime() {
setState(() {
_now = time.toString();
});
}
// State 生命週期
@override
void initState() {
print('====initState===');
super.initState();
// 監聽事件
time.addListener(_updateTime);
}
@override
Widget build(BuildContext context) {
print('====build====');
return Text(_now);
}
}
今日成果
重點回顧:
StatelessWidget
和 StatefulWidget
兩種。StatefulWidget
,並定義 State
物件。setState
通知 widget